import { Callout } from '@/components'

# Atom

Atom 컴포넌트는 Jotai의 [useAtom](https://jotai.org/docs/core/use-atom#useatom) 훅과 동일한 인터페이스를 Props로 제공하며 선언적으로 사용할 수 있습니다.

### props.atom

Jotai의 atom을 그대로 사용할 수 있습니다.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { atom } from 'jotai'

const countAtom = atom(1)

const Example = () => (
  <Atom atom={countAtom}>
    {([count, setCount]) => (
      <>
        <div>count: {count}</div>
        <button onClick={() => setCount(count + 1)}>+1</button>
      </>
    )}
  </Atom>
)
```

Async Atom일 경우 프로미스(Promise)가 해결(resolve) 되기 전까지, 부모의 Suspense에게 Promise의 pending 상태를 위임합니다.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { atom } from 'jotai'

const countAtom = atom(1)
const asyncDoubleCountAtom = atom(async (get) => {
  await delay(2000)
  return get(countAtom) * 2
})

const Example = () => (
  <Suspense fallback={'pending...'}>
    <Atom atom={asyncDoubleCountAtom}>{([count]) => <>count: {count}</>}</Atom>
  </Suspense>
)
```

### 동기

상위 컴포넌트에서 useAtom이 명확하게 드러나지 않습니다. 하위에 선언된 컴포넌트가 내부적으로 어떤 Atom을 사용하고, Suspense를 발생할지 예상하기 어렵습니다.

```tsx
// payment/page.tsx
import { Suspense } from '@suspensive/react'
import { UserInfo, ShoppingCart } from '~/components'

const PaymentPage = () => (
  <Suspense fallback={'pending...'}>
    {/* UserInfo의 내부적으로 Suspense를 발생시키는 Async Atom을 사용하는지 예상하기 어렵습니다. */}
    <UserInfo />
    {/* ShoppingCart의 내부적으로 Suspense를 발생시키는 Async Atom을 사용하는지 예상하기 어렵습니다. */}
    <ShoppingCart />
  </Suspense>
)
```

```tsx
// payment/components/UserInfo.tsx
import { useAtomValue } from '@suspensive/jotai'
import { UserAddress } from '~/components'
import { userAsyncAtom } from '~/atoms'

// 이 컴포넌트를 사용하는 입장에서 UserInfo라는 이름만으로 내부적으로 어떤 Atom을 사용하고, Suspense가 발생할지 예상하기 어렵습니다.
const UserInfo = () => {
  const data = useAtomValue(userAsyncAtom)

  return <UserAddress {...data} />
}
```

```tsx
// payment/components/ShoppingCart.tsx
import { useAtom } from 'jotai'
import { ShoppingItem } from '~/components'
import { shoppingCartAtom } from '~/atoms'

// 이 컴포넌트를 사용하는 입장에서 ShoppingCart라는 이름만으로 내부적으로 어떤 Atom을 사용하고, Suspense가 발생할지 예상하기 어렵습니다.
const ShoppingCart = () => {
  const [data] = useAtom(shoppingCartAtom)

  return (
    <>
      {data.map((item) => (
        <ShoppingItem key={item.id} {...item} />
      ))}
    </>
  )
}
```
